<?php
/**
 * Created by PhpStorm.
 * User: summercode
 * Date: 2018/12/23
 * Time: 6:14 PM
 */
namespace app\index\controller;

use app\common\controller\BaseModel;
use app\common\model\OrderModel;
use app\common\model\SettingModel;
use app\common\model\TicketModel;
use app\common\model\UserModel;
use app\common\model\WxOrderModel;
use think\Log;
use think\Request;

class TestPay
{
    private $app_id = 'wx595bfc7fcb9b012b';                                                      // Your appid
    private $mch_id = '1389731502';                                                      // Your 商户号
    private $makesign = 'Jack603337950718603337Jack603337';                                                    // Your API支付的签名(在商户平台API安全按钮中获取)
    private $parameters=NULL;
    private $notify='https://market.jackgroup.cn/index.php/minip/pay/callack';                             //配置回调地址(给pays中转文件上传到根目录下面)
    private $app_secret='514f3c8f6449f06f37d0e40cacde92d6';                                                    //Your appSecret 微信官方获取
    public $error = 0;
    public $orderid = null;

    //进行微信支付
    public function wxPay(Request $request){

        $reannumb = $this->randomkeys(10);  //生成随机数 以后可以当做 订单号
        $pays = $request->param('pays');           //获取需要支付的价格·
        $body = $request->param('body');
        $openid = $request->param('openid');
        $uid = $request->param('uid');
        $uname = $request->param('uname');
        $phone = $request->param('phone');

        $userModel = new UserModel();
        $userModel->where('id', $uid)->update([
            'name' => $uname,
            'phone' => $phone
        ]);

        #插入语句书写的地方
        $conf = $this->payconfig('Bm'.$reannumb,990, $body, $openid);
        if (!$conf || $conf['return_code'] == 'FAIL') exit("<script>alert('对不起，微信支付接口调用错误!" . $conf['return_msg'] . "');history.go(-1);</script>");
        $this->orderid = $conf['prepay_id'];
        //微信相关配置如果不正的话，进入支付页面会出现错误信息

        //生成页面调用参数
        $jsApiObj["appId"] = $conf['appid'];
        $timeStamp = time();
        $jsApiObj["timeStamp"] = "$timeStamp";
        $jsApiObj["nonceStr"] = $this->createNoncestr();
        $jsApiObj["package"] = "prepay_id=" . $conf['prepay_id'];
        $jsApiObj["signType"] = "MD5";
        $jsApiObj["paySign"] = $this->MakeSign($jsApiObj);

        $json = json_encode($jsApiObj);
        //返回支付页面，并将相关参数返回给JS
        return $json;
    }


    //订单管理
    #微信JS支付参数获取#
    protected function payconfig($no, $fee, $body, $openid)
    {
        $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        $data['appid'] = $this->app_id;
        $data['mch_id'] = $this->mch_id;                       //商户号
        $data['device_info'] = 'WEB';
        $data['body'] = $body;
        $data['out_trade_no'] = $no;                           //订单号
        $data['total_fee'] = $fee;                             //金额
        $data['spbill_create_ip'] = $_SERVER["REMOTE_ADDR"];   //ip地址
        $data['notify_url'] = $this->notify;
        $data['trade_type'] = 'JSAPI';
        $data['openid'] = $openid;                 //获取保存用户的openid
        $data['nonce_str'] = $this->createNoncestr();
        $data['sign'] = $this->MakeSign($data);


        $xml = $this->ToXml($data);
        $curl = curl_init(); // 启动一个CURL会话

        curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);

        //设置header
        curl_setopt($curl, CURLOPT_HEADER, FALSE);

        //要求结果为字符串且输出到屏幕上
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($curl, CURLOPT_POST, TRUE); // 发送一个常规的Post请求
        curl_setopt($curl, CURLOPT_POSTFIELDS, $xml); // Post提交的数据包
        curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
        $tmpInfo = curl_exec($curl); // 执行操作
        curl_close($curl); // 关闭CURL会话
        $arr = $this->FromXml($tmpInfo);
        return $arr;
    }

    /**
     *    作用：产生随机字符串，不长于32位
     */
    public function createNoncestr($length = 32){
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    /**
     *    作用：产生随机字符串，不长于32位
     */
    public function randomkeys($length)
    {
        $pattern = '1234567890123456789012345678905678901234';
        $key = null;
        for ($i = 0; $i < $length; $i++) {
            $key .= $pattern{mt_rand(0, 30)};    //生成php随机数
        }
        return $key;
    }

    /**
     * 将xml转为array
     * @param string $xml
     * @throws WxPayException
     */
    public function FromXml($xml)
    {
        //将XML转为array
        return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    }

    /**
     * 输出xml字符
     * @throws WxPayException
     **/
    public function ToXml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
            }
        }
        $xml .= "</xml>";
        return $xml;
    }

    /**
     * 生成签名
     * @return 签名，本函数不覆盖sign成员变量，如要设置签名需要调用SetSign方法赋值
     */
    protected function MakeSign($arr)
    {
        //签名步骤一：按字典序排序参数
        ksort($arr);
        $string = $this->ToUrlParams($arr);
        //签名步骤二：在string后加入KEY
        $string = $string . "&key=" . $this->makesign;
        //签名步骤三：MD5加密
        $string = md5($string);
        //签名步骤四：所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }

    /**
     * 格式化参数格式化成url参数
     */
    protected function ToUrlParams($arr)
    {
        $buff = "";
        foreach ($arr as $k => $v) {
            if ($k != "sign" && $v != "" && !is_array($v)) {
                $buff .= $k . "=" . $v . "&";
            }
        }

        $buff = trim($buff, "&");
        return $buff;
    }


    /**
     *
     * 支付回调
     * @param Request $request
     * @throws \Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function payNotify(Request $request) {

        //获取接口数据，如果$_REQUEST拿不到数据，则使用file_get_contents函数获取
        $post = $_REQUEST;
        if ($post == null) {
            $post = file_get_contents("php://input");
        }

        if ($post == null) {
            $post = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : '';
        }

        if (empty($post) || $post == null || $post == '') {
            //阻止微信接口反复回调接口  文档地址 https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_7&index=7，下面这句非常重要!!!
            $str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
            echo $str;
            exit('Notify 非法回调');
        }

        Log::write('支付日志1：', $post);
        /*****************微信回调返回数据样例*******************
        $post = '<xml>
        <return_code><![CDATA[SUCCESS]]></return_code>
        <return_msg><![CDATA[OK]]></return_msg>
        <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
        <mch_id><![CDATA[10000100]]></mch_id>
        <nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
        <sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
        <result_code><![CDATA[SUCCESS]]></result_code>
        <prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
        <trade_type><![CDATA[APP]]></trade_type>
        </xml>';
         *************************微信回调返回*****************/

        libxml_disable_entity_loader(true); //禁止引用外部xml实体

        $xml = simplexml_load_string($post, 'SimpleXMLElement', LIBXML_NOCDATA);//XML转数组

        $post_data = (array)$xml;




        $order = new WxOrderModel();
        $user = new UserModel();
        $orderModel = new OrderModel();
        $ticketModel = new TicketModel();

        $o_data = $order->where('out_trade_no' , $post_data['out_trade_no'])->find();
        if (empty($o_data)) {
            $data = [
                'transaction_id' => $post_data['transaction_id'],
                'out_trade_no' => $post_data['out_trade_no'],
                'total_fee' => $post_data['total_fee'],
                'trade_type' => $post_data['trade_type'],
                'openid' => $post_data['openid']
            ];
            $order->data($data)->save();

            $uid = $user->where('openId', $post_data['openid'])->value('id');

            $orderData = [
                'uid' => $uid,
                'order_id' => BaseModel::createOID(),
                'price' => 9.8
            ];

            $res = $orderModel->data($orderData)->save();

            $oid = $orderModel->id;
            // 如果创建订单成功
            if ($res == 1) {

                // 现金红包1个插入奖池
                $setting = new SettingModel();

                // 获取奖池
                $prizeStr = $setting->where('jack_key', 'prizeArr')->value('jack_value');

                // 奖池字符串转化为数组
                $prizeArr = explode(',', $prizeStr);

                array_push($prizeArr, mt_rand(6000, 6999));
                // 打乱数组
                shuffle($prizeArr);

                // 将打乱的数组再次转化为字符串存入数据库中
                $longText = implode(",", $prizeArr);
                $setting->where('jack_key', 'prizeArr')->update([
                    'jack_value' => $longText
                ]);

            }

            //  创建3张A5抵购券
            $arr = array();
            for ($i = 0; $i < 3; $i++) {

                $t1 = [
                    'uid' => $uid,
                    'oid' => $oid,
                    'tname' => '100元A5专用抵价券',
                    'tprice' => 100,
                    'is_all' => 0,
                    'is_pass' => 0,
                    'validate' => 1554047980,
                    't_class' => 1
                ];

                array_push($arr, $t1);

            }


            //  创建2张通用抵购券
            for ($j = 0; $j < 2; $j++) {

                $t2 = [
                    'uid' => $uid,
                    'oid' => $oid,
                    'tname' => '100元通用抵价券',
                    'tprice' => 100,
                    'is_all' => 1,
                    'is_pass' => 0,
                    'validate' => 1554047980,
                    't_class' => 1
                ];

                array_push($arr, $t2);

            }

            $ticketModel->saveAll($arr);

            // 修改用户是否有权抢券字段
            $user->where('id', $uid)->update(['is_ticket' => 1, 'status' => 1]);

            $ticketNum = $setting->where('jack_key', 'ticket')->value('jack_value');
            $setting->where('jack_key', 'ticket')->update([
                'jack_value' => --$ticketNum
            ]);

        }

        //阻止微信接口反复回调接口  文档地址 https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_7&index=7，下面这句非常重要!!!
        $str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        echo $str;


    }
}